#一 、
# 基础条件查询
# 1 基本查询
# get查询单一结果，如果不存在会抛出模型类.DeosNotExist异常
#导包
from book.models import BookInfo,PeopleInfo
#get查询单一结果 id =1
book = BookInfo.objects.get(id=1)
# 查找id=5的图书 pk：主键，目前 不存在此书，会抛出DeosNotExist异常
book = BookInfo.objects.get(pk=5)

#all查询多个结果
books = BookInfo.objects.all()

#count查询结果的数量
count = PeopleInfo.objects.count()

#2 过滤查询
"""
实现SQL中的where功能，包括
 ---filter过滤出多个结果
 ---exclude排除掉符合条件剩下的结果
 ---get过滤单一结果
对于过滤条件的使用，上述三个方法相同，故仅以filter进行讲解。

过滤条件的表达语法如下：
 ---属性名称__比较运算符=值
 ---属性名称和比较运算符间使用两个下划线，所以属性名不能包括多个下划线

#查询书名包含'湖'的图书
#查询书名以'部'结尾的图书
#查询书名为空的图书
#查询编号为1或3或5的图书
#查询编号大于3的图书
#查询1980年发表的图书
#查询1990年1月1日后发表的图书
"""
#导包
from book.models import BookInfo,PeopleInfo

#查询 编号 为1的图书
#exact 等于
BookInfo.objects.filter(id__exact=1)
#简写
BookInfo.objects.filter(id=1)
#get 方法1
BookInfo.objects.get(id=1)
#get 方法2
BookInfo.objects.get(pk=1)

#查询 书名 包含'湖'的图书
BookInfo.objects.filter(name__contains='湖')

#查询 书名 以'部'结尾的图书
BookInfo.objects.filter(name__endswith='部')

#查询 书名 为空的图书
BookInfo.objects.filter(name__isnull=True)

#查询 编号 为1或3或5的图书
#in：是否包含在范围内。
BookInfo.objects.filter(id__in=[1,3,5])

"""
 ---gt大于 (greater then)
 ---gte大于等于 (greater then equal)
 ---lt小于 (less then)
 ---lte小于等于 (less then equal)
"""
#查询 编号 大于3的图书
BookInfo.objects.filter(id__gt=3)

#查询 1980年 发表的图书
BookInfo.objects.filter(pub_date__year=1980)

#查询 1990年1月1日后 发表的图书
BookInfo.objects.filter(pub_date__gt='1990-1-1')

#二、F和Q对象
"""
1.F对象
    之前的查询都是对象的属性与常量值比较，两个属性怎么比较呢？ 答：使用F对象，被定义在django.db.models中。

语法如下：
     F(属性名)
"""
#导包
from django.db.models import F,Q
#查询 阅读量 大于等于 评论量 的图书。
BookInfo.objects.filter(readcount__gt=F('commentcount'))

#可以在F对象上使用算数运算。
#查询 阅读量 大于2倍 评论量 的图书。
BookInfo.objects.filter(readcount__gt=F('commentcount')*2)
"""
2.Q对象
     多个过滤器逐个调用表示逻辑与关系，同sql语句中where部分的and关键字。
"""
#查询 阅读量  大于20，并且 编号小于3  的图书。
BookInfo.objects.filter(readcount__gt=20,id__lt=3)

#查询 阅读量  大于20，并且 编号小于3  的图书, 只能使用Q对象实现
BookInfo.objects.filter(Q(readcount__gt=20) | Q(id__lt=3))

#查询编号不等于3的图书。
#Q对象前可以使用~操作符，表示非not。
BookInfo.objects.filter(~Q(id=3))

#三、聚合函数和排序函数
#1. 聚合函数:使用aggregate()过滤器调用聚合函数。
#   聚合函数包括：Avg平均，Count数量，Max最大，Min最小，Sum求和，被定义在django.db.models中。
from django.db.models import Sum,Max
#查询图书的总阅读量。
BookInfo.objects.aggregate(Sum('readcount'))
#查询图书最大的总阅读量
BookInfo.objects.aggregate(Max('readcount'))

#2.排序
# 使用order_by对结果进行排序
# 默认 升序排列
BookInfo.objects.all()   #默认 按照主键 升序排列
BookInfo.objects.all().order_by('readcount')  #  按照给定的 字段名(列名)进行排序

#降序
BookInfo.objects.all().order_by('-readcount')


#四、级联查询

#1.关联查询

#1.1 由一到多的访问语法：一对应的模型类对象.多对应的模型类名小写_set
# 查询 书籍 id为1的 所有人物信息
#一对应的模型类对象
book = BookInfo.objects.get(id=1)
book
# 对象，多对应的模型类名小写_set,通过all()返回所有人物
book.peopleinfo_set.all()

#1.2 由多到一的访问语法: 多对应的模型类对象.多对应的模型类中的关系类属性名
# 查询 人物 id为1的 所有人物信息
#多对应的模型类对象
people = PeopleInfo.objects.get(id=1)
people
#对象,多对应的模型类中的关系类属性名
people.book

#1.3 访问一对应的模型类关联对象的id语法:多对应的模型类对象.关联类属性_id
#查询 id=1 的人物 所属 图书的id
people = PeopleInfo.objects.get(id=1)
people.book_id

#2.关联过滤查询
#2.1 由多模型类条件查询一模型类数据:
"""
语法如下：
   关联模型类名小写__属性名__条件运算符=值
注意：如果没有"__运算符"部分，表示等于。
"""
#查询图书，要求 图书人物 为 "郭靖"
book = BookInfo.objects.filter(peopleinfo__name='郭靖')

#查询图书，要求 图书中 人物的 描述 包含"八"
book = BookInfo.objects.filter(peopleinfo__description__contains='八')


#2.2 由一模型类条件查询多模型类数据:
"""
语法如下：
    一模型类关联属性名__一模型类属性名__条件运算符=值
注意：如果没有"__运算符"部分，表示等于。
"""
#查询 书名为“天龙八部” 的 所有人物
peoples = PeopleInfo.objects.filter(book__name='天龙八部')

#查询 图书阅读量 大于30 的 所有人物
peoples = PeopleInfo.objects.filter(book__readcount__gt=30)
